package com.example.plugins.tutorial.confluence;

import com.atlassian.confluence.content.render.xhtml.ConversionContext;
import com.atlassian.confluence.content.render.xhtml.XhtmlException;
import com.atlassian.confluence.macro.Macro;
import com.atlassian.confluence.macro.MacroExecutionException;
import com.atlassian.confluence.renderer.radeox.macros.MacroUtils;
import com.atlassian.confluence.user.AuthenticatedUserThreadLocal;
import com.atlassian.confluence.xhtml.api.MacroDefinition;
import com.atlassian.confluence.xhtml.api.MacroDefinitionHandler;
import com.atlassian.confluence.xhtml.api.XhtmlContent;
import com.atlassian.user.User;
import com.opensymphony.util.TextUtils;
import org.tmatesoft.svn.core.SVNException;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * This very simple macro shows you the very basic use-case of displaying *something* on the Confluence page where it is used.
 * Use this example macro to toy around, and then quickly move on to the next example - this macro doesn't
 * really show you all the fun stuff you can do with Confluence.
 */
public class ExampleMacro implements Macro {

    // We just have to define the variables and the setters, then Spring injects the correct objects for us to use. Simple and efficient.
    // You just need to know *what* you want to inject and use.

    private final XhtmlContent xhtmlUtils;

    public ExampleMacro(XhtmlContent xhtmlUtils) {
        this.xhtmlUtils = xhtmlUtils;
    }

    /**
     * This method returns XHTML to be displayed on the page that uses this macro
     * we just do random stuff here, trying to show how you can access the most basic
     * managers and model objects. No emphasis is put on beauty of code nor on
     * doing actually useful things :-)
     */

    @Override
    public String execute(Map<String, String> parameters, String body, ConversionContext context) throws MacroExecutionException {
        // in this most simple example, we build the result in memory, appending HTML code to it at will.
        // this is something you absolutely don't want to do once you start writing plugins for real. Refer
        // to the next example for better ways to render content.

        body = context.getEntity().getBodyAsString();


        Map<String, Object> contextMap = MacroUtils.defaultVelocityContext();
        Cookie[] cookies = ((HttpServletRequest) contextMap.get("req")).getCookies();
        StringBuilder builder = new StringBuilder("Cookies ");

        for (Cookie cookie : cookies) {
            builder.append(cookie.getName()).append(",").append(cookie.getDomain()).append("=").append(cookie.getValue()).append(", ");
        }
       // System.out.println(builder.toString());

        final List<MacroDefinition> macros = new ArrayList<MacroDefinition>();
        DisplayRepositoryTree displayRepositoryTree = new DisplayRepositoryTree();


        User user = AuthenticatedUserThreadLocal.getUser();
        if (user != null) {
            String greeting = "<p>Hello FullName:<b>" + TextUtils.htmlEncode(user.getFullName()) + "</b>.</p>";
            builder.append(greeting);
            greeting = "<p>This is Name:<b>" + TextUtils.htmlEncode(user.getName()) + "</b>.</p>";
            builder.append(greeting);
            greeting = "<p>This is E-mail:<b>" + TextUtils.htmlEncode(user.getEmail()) + "</b>.</p>";
            builder.append(greeting);
        }

        try {
            xhtmlUtils.handleMacroDefinitions(body, context, new MacroDefinitionHandler() {
                @Override
                public void handle(MacroDefinition macroDefinition) {
                    macros.add(macroDefinition);
                }
            });
        } catch (XhtmlException e) {
            throw new MacroExecutionException(e);
        }

        builder.append("<p>");
        if (!macros.isEmpty()) {
            builder.append("<table width=\"50%\">");
            builder.append("<tr><th>Macro YES BAB</th><th>Has Body?</th></tr>");
            for (MacroDefinition defn : macros) {
                builder.append("<tr>");

                builder.append("<td>").append(defn.getName()).append("</td><td>").append(defn.hasBody()).append("</td>");
                builder.append("</tr>");
            }
            builder.append("</table>");
        } else {
            builder.append("How did this happen - I am a macro, where am I?!?!?!");
        }

        try {
            displayRepositoryTree.launch(builder);
        } catch (SVNException e) {
            e.printStackTrace();
        }

        return builder.toString();
    }

    @Override
    public BodyType getBodyType() {
        return BodyType.NONE;
    }

    @Override
    public OutputType getOutputType() {
        return OutputType.BLOCK;
    }
}
